home *** CD-ROM | disk | FTP | other *** search
- /* $XConsortium: objects.c,v 1.11 94/03/23 14:28:05 gildea Exp $ */
- /* Copyright International Business Machines, Corp. 1991
- * All Rights Reserved
- * Copyright Lexmark International, Inc. 1991
- * All Rights Reserved
- *
- * License to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of IBM or Lexmark not be
- * used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission.
- *
- * IBM AND LEXMARK PROVIDE THIS SOFTWARE "AS IS", WITHOUT ANY WARRANTIES OF
- * ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO ANY
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
- * AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. THE ENTIRE RISK AS TO THE
- * QUALITY AND PERFORMANCE OF THE SOFTWARE, INCLUDING ANY DUTY TO SUPPORT
- * OR MAINTAIN, BELONGS TO THE LICENSEE. SHOULD ANY PORTION OF THE
- * SOFTWARE PROVE DEFECTIVE, THE LICENSEE (NOT IBM OR LEXMARK) ASSUMES THE
- * ENTIRE COST OF ALL SERVICING, REPAIR AND CORRECTION. IN NO EVENT SHALL
- * IBM OR LEXMARK BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
- * THIS SOFTWARE.
- */
-
- /*
- * OBJECTS Module - TYPE1IMAGER Objects Common Routines
- *
- * This module defines and implements the C structures that represent
- * objects in the TYPE1IMAGER. All common routines for manipulating these
- * objects are defined in this module. Specific routines for
- * specific objects are defined in the modules that deal with that
- * object type.
- *
- *
- * &author. Jeffrey B. Lotspiech (lotspiech@almaden.ibm.com)
- */
-
-
- /************
- Include Files
-
- The included files are:
- *************/
-
- /*
- * The following two includes are C standards; we include them because we
- * use 'toupper' and the 'str'-type functions in this module. Potentially
- * these may be defined as macros; if these ".h" files do not exist on your
- * system it is a pretty safe bet that these are external entry points and
- * you do do not need to include these header files.
- */
- #include <ctype.h>
-
- /* moved these includes from above the */
- /* was included first (it contains com- */
- /* piler defines). dsr 081291 */
-
- #ifndef T1GST
- #include "global.h"
- #endif
-
-
- char MustCheckArgs = TRUE;
- char MustTraceCalls = FALSE;
- char MustCrash = TRUE;
- char InternalTrace = TRUE;
- char LineIOTrace = TRUE;
-
- char ProcessHints = TRUE;
-
- char SaveFontPaths = TRUE;
-
- short CRASTERCompressionType = 1;
-
- char ConicDebug = 0;
- char LineDebug = 0;
- char RegionDebug = 0;
- char PathDebug = 0;
- char FontDebug = 0;
- char SpaceDebug = 0;
- char StrokeDebug = 0;
- char MemoryDebug = 0;
- char HintDebug = 0;
- char ImageDebug = 0;
- char OffPageDebug = 0;
-
- short CachedChars = 0x7FFF;
- short CachedFonts = 0x7FFF;
- int CacheBLimit = 12500;
- char Continuity = 2;
-
-
- //static char *TypeFmt(int type);
- //static void ObjectPostMortem(struct xobject *obj);
-
-
- /*
- * Note that entry points that are intended for use external to TYPE1IMAGER
- * begin with the characters xi. Macros are used to make the names
- * more mnemonic.
- */
-
- /*
- * Note that entry points that intended for use within TYPE1IMAGER, but
- * which must be global because they are used across module boundaries,
- * begin with the characters I_. Macros are used to make the names
- * more mnemonic.
- *
- * Entry points totally within a module use mnemonic names and are
- * declared static. One of the compilers I used had a bug when
- * static functions were passed as addresses. Thus, some functions
- * which are logically "static" are not so declared.
- *
- * Note also the trick of declaring routines, like Consume(), with a
- * variable number of arguments. To avoid the restrictions on variable
- * numbers of arguments in the macro processor, we just replace the
- * text 'Consume' with 'I_Consume'.
- */
-
-
- /*
- * RefRoll() Macro to Detect References Count Rollover
- *
- * The following macro is designed to check for reference count rollover.
- * A return value of TRUE means rollover has not occurred; a return value
- * of FALSE means we cannot increment the reference count. Note also that
- * those functions that use this macro must decrement the reference count
- * afterwards. 3-26-91 PNM
- */
- #define RefRoll(obj) (++(obj)->references > 0)
-
-
- /*
- * Allocate() - Allocating a Memory Block
- *
- * Allocate returns a pointer to memory object that is a copy of
- * the template passed (if any). In addition, extra bytes may be
- * allocated contiguously with the object. (This may be useful for
- * variable size objects such as edge lists. See :hdref refid=regions..)
- *
- * Allocate() always returns a non-immortal object, even if the template is
- * immortal. Therefore a non-NULL template must have a "flag" byte.
- *
- * If the template is NULL, then 'size' bytes are cleared to all NULLs.
- *
- * If the template is non-NULL, a new object is allocated in memory.
- * It therefore seems logical that its reference count field should be
- * set to 1. So, a nun-NULL template must also have a "references" field.
- * PNM 3-26-91
- */
- struct xobject *t1_Allocate(
- int size, /* number of bytes to allocate & initialize */
- struct xobject *template, /* example structure to allocate */
- int extra) /* any extra uninitialized bytes needed contiguously */
- {
- extern char *xiMalloc();
-
- struct xobject *r;
-
- /*
- * round up 'size' and 'extra' to be an integer number of 'long's:
- */
- size = (size + sizeof(long) - 1) & -(int)sizeof(long);
- extra = (extra + sizeof(long) - 1) & -(int)sizeof(long);
-
- if (size + extra <= 0)
- t1_abort("Non-positive allocate?");
- r = (struct xobject *)xiMalloc(size + extra);
-
- while (r == NULL)
- {
- if (!GimeSpace())
- {
- IfTrace1(TRUE, "malloc attempted %d bytes.\n",
- size + extra);
- t1_abort("We have REALLY run out of memory");
- }
- r = (struct xobject *)xiMalloc(size + extra);
- }
-
- /*
- * copy the template into the new memory:
- */
- if (template != NULL)
- {
- /* Added references count decrement if template is not permanent.
- This is for the case where Allocate is called by a Dupxxxx
- function, which was in turn called by Unique(). (PNM) */
- if (!ISPERMANENT(template->flag))
- --template->references;
- LONGCOPY(r, template, size);
- r->flag &= ~(ISPERMANENT(ON) | ISIMMORTAL(ON));
- /* added reference field 3-2-6-91 PNM */
- r->references = 1;
- }
- else
- {
- register char **p1;
-
- for (p1 = (char **)r; size > 0; size -= sizeof(char *))
- *p1++ = NULL;
- }
-
- // if (MemoryDebug > 1)
- // {
- // register long *L;
- //
- // L = (long *)r;
- // IfTrace4(TRUE, "Allocating at %x: %x %x %x\n",
- // L, L[-1], L[0], L[1]);
- // }
-
- return (r);
- }
-
-
- /*
- * Free() - Frees an Allocated Object
- *
- * This routine makes a sanity check to make sure the "type" field of the
- * standard object structure has not been cleared. If the object is
- * not a standard structure, then the macro "NonObjectFree" is available
- * that does not perform this check.
- *
- * In either case, the object must not be the NULL pointer. This preserves
- * portability, as the C system xiFree() will not always accept NULL.
- */
- void t1_Free(struct xobject *obj)
- {
- if (obj->type == INVALIDTYPE)
- t1_abort("Free of already freed object?");
- obj->type = INVALIDTYPE;
-
- // if (MemoryDebug > 1)
- // {
- // register long *L;
- //
- // L = (long *)obj;
- // IfTrace4(TRUE, "Freeing at %x: %x %x %x\n", L, L[-1], L[0], L[1]);
- // }
-
- xiFree(obj);
- }
-
-
- /*
- * Permanent() - Makes an Object Permanent
- *
- * Real simple--just set a flag. Every routine that consumes its objects
- * (which is almost every user entry) must check this flag, and not consume
- * the object if it is set.
- *
- * If a temporary object is made permanent, and there is more than one
- * reference to it, we must first Copy() it, then set the ISPERMANENT
- * flag. Note also that the reference count must be incremented when an
- * object is changed from temporary to permanent (see the ISUNIQUE macro).
- *
- * Note that the purpose of this function is to convert an object into a
- * permanent object:
- * If it was permanent to begin with, we do nothing;
- * If it was temporary and unique, we set the PERMANENT flag and increment
- * the reference count;
- * If it was temporary and nonunique, we must make a unique Copy(), set
- * the PERMANENT flag, and set the reference count to 2. We must also
- * decrement the original object's reference count, because what we have
- * done is to change one of the old temporary handles to a permanent one.
- * 3-26-91 PNM
- */
- struct xobject *t1_Permanent(struct xobject *obj)
- {
- // IfTrace1((MustTraceCalls), "Permanent(%z)\n", obj);
-
- if ((obj != NULL) && (!(ISPERMANENT(obj->flag))))
- {
- /* there is a non-NULL, temporary object to be made permanent.
- * If there are multiple references to this object, first get
- * a new COPY().
- * Note also that we have to decrement the reference count if
- * we do a Copy() here, because we are consuming the temporary
- * argument passed, and returning a unique, permanent one.
- */
- if (obj->references > 1)
- {
- obj = Copy(obj);
- }
- /* now set the permanent flag, and increment the reference
- * count, since a temporary object has now become permanent. */
- obj->references++;
- obj->flag |= ISPERMANENT(ON);
- }
- return (obj);
- }
-
-
- /*
- * Temporary() - Undoes the Effect of "Permanent()"
- *
- * This simply resets the "ISPERMANENT" flag.
- *
- * If a permanent object is made temporary, and there is more than one reference
- * to it, we must first Copy() it, then reset the ISPERMANENT flag. However,
- * if the permanent object has obly one reference, we need only decrement the
- * reference count ( and reset the flag).
- *
- * Note that this function, in the case of a PERMANENT argument, basically
- * converts the PERMANENT handle to a TEMPORARY one. Thus, in the case of
- * a nonunique, permanent argument passed, we not only make a Copy(),
- * we also decrement the reference count, to reflect the fact that we have
- * lost a permanent handle and gained a temporary one.
- * PNM 3-2-6-91
- */
- struct xobject *t1_Temporary(struct xobject *obj)
- {
- // IfTrace1((MustTraceCalls), "Temporary(%z)\n", obj);
-
- if (obj != NULL)
- {
- /* if it's already temporary, there's nothing to do. */
- if ISPERMANENT(obj->flag)
- {
- /* if there are multiple references to this object, get a
- * Copy we can safely alter. Recall that the reference count
- * is incremented for permanent objects.
- * Recall further that Copy returns an object with the
- * same flag state and a reference count of 2 (for PERMANENT
- * objects).
- * Thus, regardless of whether or not we need to copy a
- * permanent object, we still decrement its reference
- * count and reset the flag.
- */
- if (obj->references != 2 || ISIMMORTAL(obj->flag))
- {
- /* not unique; consume handle, get a temporary Copy! */
- obj = Copy(obj);
- }
- /* else decrement the reference count (since it's going from
- permanent to temporary) and clear the flag. */
- else
- {
- obj->references--;
- obj->flag &= ~ISPERMANENT(ON);
- }
- }
- }
- return (obj);
- }
-
-
- /*
- * Dup() - Duplicate an Object
- *
- * Dup will increment the reference count of an object, only making a
- * Copy() if needed.
- * Note that Dup() retains the state of the permanent flag.
- * 3-26-91 PNM
- */
- struct xobject *t1_Dup(struct xobject *obj)
- {
- char oldflag; /* copy of original object's flag byte */
-
- // IfTrace1((MustTraceCalls), "Dup(%z)\n", obj);
-
- if (obj == NULL)
- return (NULL);
- /* An immortal object must be Copy'ed, so that we get a mortal
- copy of it, since we try not to destroy immortal objects. */
- if (ISIMMORTAL(obj->flag))
- return (Copy(obj));
-
- /* if incrementing the reference count doesn't cause the count
- to wrap, simply return the object with the count bumped. Note
- that the RefRoll macro increments the count to perform the
- rollover check, so we must decrement the count. */
- if (RefRoll(obj))
- return (obj);
-
- /* that didn't work out, so put the count back and call Copy(). */
- --obj->references;
- oldflag = obj->flag;
- obj = Copy(obj);
- if (ISPERMANENT(oldflag))
- obj = Permanent(obj);
- return (obj);
- }
-
-
- /*
- * Copy() - Make a New Copy of an Object
- *
- * This is the generic Copy() where the object type is unknown. There
- * are specific Copyxxx functions for known object types.
- *
- * Copy will create a NEW temporary object, and WILL NOT simply bump the
- * reference count.
- *
- * Sometimes duplicating an object is just as simple as Allocating with it
- * as a template. But other objects are complicated linked lists. So, we
- * let each module provide us a routine (or macro) that duplicates the
- * objects it knows about.
- */
- struct xobject *t1_Copy(struct xobject *obj)
- {
- if (obj == NULL)
- return (NULL);
-
- if (ISPATHTYPE(obj->type))
- obj = (struct xobject *)CopyPath(obj);
- else
- switch (obj->type)
- {
- case SPACETYPE:
- obj = (struct xobject *)CopySpace(obj);
- break;
- case FONTTYPE:
- obj = (struct xobject *)CopyFont(obj);
- break;
- case REGIONTYPE:
- obj = (struct xobject *)CopyRegion(obj);
- break;
- case PICTURETYPE:
- obj = (struct xobject *)CopyPicture(obj);
- break;
- case LINESTYLETYPE:
- obj = (struct xobject *)CopyLineStyle(obj);
- break;
- case STROKEPATHTYPE:
- obj = (struct xobject *)CopyStrokePath(obj);
- break;
- case CLUTTYPE:
- obj = (struct xobject *)CopyCLUT(obj);
- break;
- default:
- return (ArgErr("Copy: invalid object", obj, NULL));
- }
-
- return (obj);
- }
-
-
- /*
- * Destroy() - Destroys an Object
- *
- * This can get complicated. Just like with Copy(), we let the experts
- * handle it.
- */
- struct xobject *t1_Destroy(struct xobject *obj)
- {
- IfTrace1((MustTraceCalls), "Destroy(%z)\n", obj);
-
- if (obj == NULL)
- return (NULL);
- if (ISIMMORTAL(obj->flag))
- {
- IfTrace1(TRUE, "Destroy of immortal object %z ignored\n", obj);
- return (NULL);
- }
- if (ISPATHTYPE(obj->type))
- KillPath(obj);
- else
- {
- switch (obj->type)
- {
- case REGIONTYPE:
- KillRegion(obj);
- break;
- case SPACETYPE:
- KillSpace(obj);
- break;
- case LINESTYLETYPE:
- KillLineStyle(obj);
- break;
- case FONTTYPE:
- KillFont(obj);
- break;
- case PICTURETYPE:
- KillPicture(obj);
- break;
- case STROKEPATHTYPE:
- KillStrokePath(obj);
- break;
- case CLUTTYPE:
- KillCLUT(obj);
- break;
- default:
- return (ArgErr("Destroy: invalid object", obj, NULL));
- }
- }
- return (NULL);
- }
-
-
- /*
- * An object is unique (and directly alterable) if there is only one
- * reference to it, and it is not permanent (in which case we increment
- * the reference count, so we don't have to check the permanent bit).
- * 3-26-91 PNM
- *
- * Note the rules for making a unique object:
- * &drawing.
- * IF (obj->references = 1) return(obj);
- * ELSE (references > 1)
- * IF (ISPERMANENT(obj->flag)) return(Dupxxx(obj));
- * ELSE (nonunique, temporary object!)
- * obj->references--; return(Dupxxx(obj));
- * &edrawing.
- * If we must make a Copy of a nonunique, temporary object, we decrement
- * reference count of the original object!
- */
-
-
- /*
- * Unique() - Make a Unique Object
- *
- * Here is a generic 'Unique' function if the object type is not known.
- * Why didn't we build it with the MAKEUNIQUE macro, you ask? Well, we
- * used to, but there is at least one damn compiler in the world that
- * raises errors if the types of an "(a) ? b : c" expression do not match.
- * Also, when we changed Dup() to retain the permanent/temporary flag, we
- * wanted to make sure "Unique" always returned a temporary object.
- *
- * Note that we cannot use Dup() to create a copy of the object in question,
- * because Dup() may simply bump the reference count, and not return a
- * unique copy to us. That is why we use t1_Copy().
- *
- * The purpose of this function is to make sure we have a copy of an object
- * that we can safely alter:
- *
- * If we have a unique, temporary object, we simply return the argument.
- * If we have a nonunique, temporary object, we have to make a new copy
- * of it, and decrement the reference count of the original object, to reflect
- * the fact that we traded temporary handles.
- * If we have a permanent object, we make a temporary copy of it, but
- * we do not decrement the reference count of the original permanent object,
- * because permanent objects, by definition, are persistent. 3-2-6-91 PNM
- */
- struct xobject *t1_Unique(struct xobject *obj)
- {
- /* if the original object is not already unique, make a unique
- copy...Note also that if the object was not permanent, we must
- consume the old handle! 3-26-91 PNM
- NOTE : consumption of the old handle moved to Allocate. 4-18-91 */
- if (!obj || obj->references == 1)
- return (obj);
-
- obj = Copy(obj);
- /* and make sure we return a temporary object ! */
- if (ISPERMANENT(obj->flag))
- {
- obj->flag &= ~ISPERMANENT(ON);
- obj->references--;
- }
- return (obj);
- }
-
-
- /*
- * Initialization, Error, and Debug Routines
- *
- * Declarations for Debug Purposes
- *
- * We declare all the debug flags here.
- */
-
- char *ErrorMessage = NULL;
-
-
- #ifdef AMISHDEBUG
- /*
- * Pragmatics() - Set/Reset Debug Flags
- *
- * We provide a controlled way for the TYPE1IMAGER user to set and reset
- * our debugging and tracing:
- */
- void Pragmatics(
- char *username, /* name of the flag */
- int value) /* value to set it to */
- {
- char *p; /* temporary loop variable */
- #define NAMESIZE 40
- char name[NAMESIZE]; /* buffer to store my copy of 'username' */
-
- if (strlen(username) >= (unsigned) NAMESIZE)
- t1_abort("Pragmatics name too large");
- strcpy(name, username);
- for (p = name; *p != '\0'; p++)
- *p = toupper(*p);
-
- if (!strcmp(name, "ALL"))
- MustTraceCalls = InternalTrace = /* MustCrash = */
- LineIOTrace = value;
-
- else if (!strcmp(name, "LINEIOTRACE"))
- LineIOTrace = value;
-
- else if (!strcmp(name, "TRACECALLS"))
- MustTraceCalls = value;
-
- else if (!strcmp(name, "CHECKARGS"))
- MustCheckArgs = value;
-
- else if (!strcmp(name, "PROCESSHINTS"))
- ProcessHints = value;
-
- else if (!strcmp(name, "SAVEFONTPATHS"))
- SaveFontPaths = value;
-
- else if (!strcmp(name, "CRASTERCOMPRESSIONTYPE"))
- CRASTERCompressionType = value;
-
- else if (!strcmp(name, "CRASHONUSERERROR"))
- MustCrash = value;
-
- else if (!strcmp(name, "DEBUG"))
- StrokeDebug = SpaceDebug = PathDebug = ConicDebug = LineDebug =
- RegionDebug = MemoryDebug = FontDebug =
- HintDebug = ImageDebug = OffPageDebug = value;
-
- else if (!strcmp(name, "CONICDEBUG"))
- ConicDebug = value;
-
- else if (!strcmp(name, "LINEDEBUG"))
- LineDebug = value;
-
- else if (!strcmp(name, "REGIONDEBUG"))
- RegionDebug = value;
-
- else if (!strcmp(name, "PATHDEBUG"))
- PathDebug = value;
-
- else if (!strcmp(name, "SPACEDEBUG"))
- SpaceDebug = value;
-
- else if (!strcmp(name, "STROKEDEBUG"))
- StrokeDebug = value;
-
- else if (!strcmp(name, "MEMORYDEBUG"))
- MemoryDebug = value;
-
- else if (!strcmp(name, "FONTDEBUG"))
- FontDebug = value;
-
- else if (!strcmp(name, "HINTDEBUG"))
- HintDebug = value;
-
- else if (!strcmp(name, "IMAGEDEBUG"))
- ImageDebug = value;
-
- else if (!strcmp(name, "OFFPAGEDEBUG"))
- OffPageDebug = value;
-
- //#ifdef MC68000
- ///*
- //The following pragmatics flag turns on or off instruction histograming
- //for performance analysis. It is only defined in the Delta card
- //environment.
- //*/
- // else if (!strcmp(name, "PROFILE"))
- // {
- // if (value)
- // StartProfile();
- // else
- // StopProfile();
- // }
- //#endif
- else if (!strcmp(name, "FLUSHCACHE"))
- {
- #ifdef notdef
- while (GimeSpace())
- {;
- }
- #endif
- }
-
- else if (!strcmp(name, "CACHEDCHARS"))
- CachedChars = (value <= 0) ? 1 : value;
-
- else if (!strcmp(name, "CACHEDFONTS"))
- CachedFonts = (value <= 0) ? 1 : value;
-
- else if (!strcmp(name, "CACHEBLIMIT"))
- CacheBLimit = value;
-
- else if (!strcmp(name, "CONTINUITY"))
- Continuity = value;
-
-
- else
- {
- // printf("Pragmatics flag = '%s'\n", name);
- ArgErr("Pragmatics: flag not known", NULL, NULL);
- }
- return;
- }
- #endif
-
-
- /*
- * Consume() - Consume a List of Arguments
- *
- * This general purpose routine is provided in the case where the object
- * type(s) to be consumed are unknown or not yet verified, and/or it is
- * not known whether the object is permanent.
- *
- * If the type of the argument is known, it is faster to directly consume
- * that type, for example, ConsumeRegion() or ConsumePath(). Furthermore,
- * if it is already known that the object is temporary, it is faster to
- * just kill it rather than consume it, for example, KillSpace().
- */
- void Consume(int n, struct xobject *obj1, struct xobject *obj2, struct xobject *obj3)
- {
- switch (n)
- {
-
- case 0:
- return;
-
- case 1:
- if (obj1 != NULL && !ISPERMANENT(obj1->flag))
- Destroy(obj1);
- return;
-
- case 2:
- if (obj1 != NULL && !ISPERMANENT(obj1->flag))
- Destroy(obj1);
- if (obj2 != NULL && !ISPERMANENT(obj2->flag))
- Destroy(obj2);
- return;
-
- case 3:
- if (obj1 != NULL && !ISPERMANENT(obj1->flag))
- Destroy(obj1);
- if (obj2 != NULL && !ISPERMANENT(obj2->flag))
- Destroy(obj2);
- if (obj3 != NULL && !ISPERMANENT(obj3->flag))
- Destroy(obj3);
- return;
-
- default:
- t1_abort("Consume: too many objects");
- }
- }
-
-
- /*
- * TypeErr() - Handles "Invalid Object Type" Errors
- */
- struct xobject *t1_TypeErr(
- char *name, /* Name of routine (for error message) */
- struct xobject *obj, /* Object in error */
- int expect, /* type expected */
- struct xobject *ret) /* object to return to caller */
- {
- static char typemsg[80];
-
- if (MustCrash)
- LineIOTrace = TRUE;
-
- // sprintf(typemsg, "Wrong object type in %s; expected %s.\n",
- // name, TypeFmt(expect), TypeFmt(obj->type));
- // sprintf(typemsg, "Wrong object type in %s\n", name);
- strcpy(typemsg, "Wrong object type in ");
- strcat(typemsg, name);
- strcat(typemsg, "\n");
- // IfTrace0(TRUE, typemsg);
-
- // ObjectPostMortem(obj);
-
- if (MustCrash)
- t1_abort("Terminating because of CrashOnUserError...");
- else
- ErrorMessage = typemsg;
-
- /* changed ISPERMANENT to ret->references > 1 3-26-91 PNM */
- if (ret != NULL && (ret->references > 1))
- ret = Dup(ret);
- return (ret);
- }
-
-
- #ifdef AMISHDEBUG
- /*
- * TypeFmt() - Returns Pointer to English Name of Object Type
- *
- * This is a subroutine of TypeErr().
- */
- static char *TypeFmt(int type)
- {
- char *r;
-
- if (ISPATHTYPE(type))
- if (type == TEXTTYPE)
- r = "path or region (from TextPath)";
- else
- r = "path";
- else
- {
- switch (type)
- {
- case INVALIDTYPE:
- r = "INVALID (previously consumed?)";
- break;
- case REGIONTYPE:
- r = "region";
- break;
- case SPACETYPE:
- r = "XYspace";
- break;
- case LINESTYLETYPE:
- r = "linestyle";
- break;
- case FONTTYPE:
- r = "font";
- break;
- case PICTURETYPE:
- r = "picture";
- break;
- case STROKEPATHTYPE:
- r = "path (from StrokePath)";
- break;
- default:
- r = "UNKNOWN";
- break;
- }
- }
- return (r);
- }
- #endif /* AMISHDEBUG */
-
-
- #ifdef AMISHDEBUG
- /*
- * ObjectPostMortem() - Prints as Much as We Can About a Bad Object
- *
- * This is a subroutine of TypeErr() and ArgErr().
- */
- static void ObjectPostMortem(struct xobject *obj)
- {
- extern struct XYspace *USER;
-
- Pragmatics("Debug", 10);
- IfTrace2(TRUE, "Bad object is of %s type %z\n", TypeFmt(obj->type), obj);
-
- IfTrace0((obj == (struct xobject *)USER),
- "Suspect that InitImager() was omitted.\n");
- Pragmatics("Debug", 0);
- }
- #endif /* AMISHDEBUG */
-
-
- /*
- * ArgErr() - Invalid Argument Passed to a Routine
- *
- * A common routine to report argument errors. It is usually called
- * is returned to the caller in case MustCrash is FALSE and ArgErr
- * returns to its caller.
- */
-
- struct xobject *t1_ArgErr(
- char *string, /* description of error */
- struct xobject *obj, /* object, if any, that was in error */
- struct xobject *ret) /* object returned to caller or NULL */
- {
- if (MustCrash)
- LineIOTrace = TRUE;
- IfTrace1(TRUE, "ARGUMENT ERROR-- %s.\n", string);
- // if (obj != NULL)
- // ObjectPostMortem(obj);
- if (MustCrash)
- t1_abort("Terminating because of CrashOnUserError...");
- else
- ErrorMessage = string;
- return (ret);
- }
-
-
- /*
- * t1_abort() - Crash Due to Error
- *
- * Defined in objects.h to be FatalError(), the server's abort routine.
- */
-
-
- /*
- * REAL Miscellaneous Stuff
- * ErrorMsg() - Return the User an Error Message
- */
- char *ErrorMsg(void)
- {
- char *r;
-
- r = ErrorMessage;
- ErrorMessage = NULL;
- return (r);
- }
-
-